Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Collection expressions: type inference from spread elements #69856

Merged
merged 3 commits into from
Sep 12, 2023

Conversation

cston
Copy link
Member

@cston cston commented Sep 8, 2023

See Type inference:

An input type inference is made from an expression E to a type T in the following way:

  • If E is a collection expression with elements Eᵢ, and T is a type with an iteration type Tₑ or T is a nullable value type T0? and T0 has an iteration type Tₑ, then an input type inference is made from each Eᵢ to Tₑ.
  • If E is a collection expression spread element with an iteration type Tₑ, then a lower-bound inference is made from Tₑ to T.
  • [existing rules from first phase] ...

Fixes #69706

Relates to test plan #66418

@dotnet-issue-labeler dotnet-issue-labeler bot added Area-Compilers untriaged Issues and PRs which have not yet been triaged by a lead labels Sep 8, 2023
@@ -2675,6 +2675,135 @@ static void Main(string[] args)
Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "F").WithArguments("Program.F<T>(System.Func<T[]>)").WithLocation(9, 17));
}

[Fact]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

workitem.

@cston cston marked this pull request as ready for review September 8, 2023 00:10
@cston cston requested a review from a team as a code owner September 8, 2023 00:10
@@ -615,6 +615,10 @@ private void MakeExplicitParameterTypeInferences(Binder binder, BoundExpression
{
MakeCollectionExpressionTypeInferences(binder, (BoundUnconvertedCollectionExpression)argument, target, kind, ref useSiteInfo);
}
else if (argument.Kind == BoundKind.CollectionExpressionSpreadElement)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find it super confusing that this parameter's name is argument when it seems like it might be any subexpression of an argument. Not for this PR to fix, though.

}

// https://github.com/dotnet/roslyn/issues/68786: Ignoring top-level nullability of enumeratorInfo.ElementType.
LowerBoundInference(TypeWithAnnotations.Create(enumeratorInfo.ElementType), target, ref useSiteInfo);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not use ElementTypeWithAnnotations?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like this could break something and cause us to not infer a type as nullable where we should. Please make sure to test something like:

M([..[default(string?)]]);
void M<T>(T[] arr);

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I hadn't noticed ElementTypeWithAnnotations previously.

I've added a couple of tests for inferring nullability but we are still not handling collection expressions in NullableWalker. If possible, I'd prefer to handle this when fixing #68786.

dynamic x = new[] { 2, 3 };
var y = F([..x]);
y.Report(includeType: true);
var z = F([1, ..x]);
Copy link
Contributor

@RikkiGibson RikkiGibson Sep 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: might be nice to show a case with multiple spread arguments. #Resolved

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added to TypeInference_Spread_01.

CompileAndVerify(new[] { source, s_collectionExtensions }, expectedOutput: "(System.Object[]) [1, 2, 3], ");
}

// If we allow inference from a spread element _expression_ rather than simply
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would def want to do this eventually. I feel like if we can make return [null] "just work" then return [..[null]] should also just work.

Copy link
Member

@333fred 333fred left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done review pass

@cston cston merged commit bd8a9f5 into dotnet:main Sep 12, 2023
25 checks passed
@cston cston deleted the inference-spread branch September 12, 2023 17:54
@ghost ghost added this to the Next milestone Sep 12, 2023
@Cosifne Cosifne modified the milestones: Next, 17.8 P3 Sep 25, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-Compilers New Feature - Collection Expressions untriaged Issues and PRs which have not yet been triaged by a lead
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Collection expressions: generic method type inference not working when spreading IEnumerable<T>
6 participants